#ifndef REMOTE_PARTY_H_
#define REMOTE_PARTY_H_

#include <string>
#include <map>
#include <semaphore.h>

enum srv_state { 
	CONN = 0, 
	DISCONN = 1
};

/* Size of the circular buffers used for socket communication */
#define CIRCULAR_BUF_SIZE	10	

struct buff_struct {
	std::string			mess[CIRCULAR_BUF_SIZE];
	
	int					nextin;
	int					nextout;
	sem_t				empty_sem;
	sem_t				full_sem;
	sem_t				put_mutex; // @p
	sem_t				get_mutex; // @c
};
typedef struct buff_struct buff_t;


/**  ~~~~~ REMOTE SERVERS ~~~~~ */

class remote_srv{
public:
	remote_srv ( const std::string& remote_ip,
			int remote_port );
	~remote_srv();

	srv_state get_conn_state();
	std::string get_ip();
	int get_sock();
	void connect();
	void write_to_remote_srv(const std::string& data);
	void send_data_to_remote_srv();
	void add_data_to_buffer(const std::string& data);
	int read_from_remote_srv(void* data, int len);
	void disconnect();
	void print();

private:

	std::string ip;
	int port;
	srv_state state;
	int sock;
	buff_t buffer;
};

/* Container of the remote servers. */
class remote_srv_list{
public:
	remote_srv_list();
	~remote_srv_list();

	void lock_list() const;
	void unlock_list() const;
	
	void add_element(remote_srv* server);
	remote_srv* get_element(const std::string& ip) const;
	void del_element(const std::string& ip);

private:
	std::map<std::string, remote_srv*> container;
	
	//mutex is mutable because lock and unlock must also be used in const functions 
	mutable pthread_mutex_t mutex;

};


/**  ~~~~~ REMOTE CLIENTS ~~~~~ */

struct r_client_data {
	std::string ip;
	int socket; 
	bool read_size_flag; // = true
	uint32_t mess_size; // = 0
};

/* Container of the remote clients. */
class remote_cli_list{
public:
	remote_cli_list();
	~remote_cli_list();

	void lock_list() const;
	void unlock_list() const;
	
	void add_element(r_client_data* remote_cli);
	r_client_data* get_element(const std::string& ip) const;
	void del_element(const std::string& ip);

private:
	std::map<std::string, r_client_data*> container;
	
	//mutex is mutable because lock and unlock must also be used in const functions 
	mutable pthread_mutex_t mutex;

};


#endif /*REMOTE_PARTY_H_*/
